﻿Imports System.Xml
Imports System.IO
Imports System.Text
Imports System.Data
Imports Microsoft.WindowsMobile.Forms

Module ClsFunctions

    Public Function GetNodeTypeDouble(ByRef xmld As XmlDocument, ByVal node As String) As Nullable(Of Double)
        Try
            Dim Val As String = xmld.SelectNodes(node).Item(0).InnerText
            If Val = "" Then
                Return Nothing
            Else
                Return CType(ChangeDecimalSeparator(Val, ".", ","), Double)
            End If
        Catch ex As Exception
            Return Nothing
        End Try
    End Function

    Public Function GetNodeTypeInteger(ByRef xmld As XmlDocument, ByVal node As String) As Nullable(Of Integer)
        Try
            Dim Val As String = xmld.SelectNodes(node).Item(0).InnerText
            If Val = "" Then
                Return Nothing
            Else
                Return CType(ChangeDecimalSeparator(Val, ".", ","), Integer)
            End If
        Catch ex As Exception
            Return Nothing
        End Try
    End Function

    Public Function ChangeDecimalSeparator(ByVal sval As String, ByVal smotifIn As String, ByVal smotifOut As String) As String
        Try
            If sval = "" Then
                Return sval
            Else
                Return Replace(sval, smotifIn, smotifOut)
            End If
        Catch ex As Exception
            Throw New Exception(ex.Message)
        End Try
    End Function

    '################################################################################################
    '       Fonctions relatives à la manipulation de l'object liste d'observation 
    '################################################################################################
    '""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    'Fonction qui renvoie un tableau correspondant à la liste des observations
    'OUT : 
    '   DataTable : Tableau simplifié des valeurs contenu dans lstStations
    '""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    Public Function ExportListObsToDataTable() As DataTable
        Try
            Dim table As DataTable = New DataTable
            'Création des colonnes
            table.Columns.Add("Date")
            table.Columns.Add("Taxon")
            table.Columns.Add("Nom_Protocole")
            table.Columns.Add("Champ_1")
            table.Columns.Add("TypeCh1")
            table.Columns.Add("Unite1")
            table.Columns.Add("Valeur1")
            table.Columns.Add("Champ_2")
            table.Columns.Add("TypeCh2")
            table.Columns.Add("Unite2")
            table.Columns.Add("Valeur2")
            'table.Columns.Add("Nb ind.")
            'table.Columns.Add("Abondance")
            'table.Columns.Add("Distance") 'ajout protocole Zambra
            'table.Columns.Add("Occupe") 'ajout protocole Zambra
            table.Columns.Add("Wpt")
            table.Columns.Add("Lon.")
            table.Columns.Add("Lat.")
            table.Columns.Add("Alt.")
            table.Columns.Add("Precision")
            table.Columns.Add("Site")
            table.Columns.Add("Commentaires")
            table.Columns.Add("Obs1")
            table.Columns.Add("Obs2")
            table.Columns.Add("Nb Obs")
            'Remplissage du tableau :
            'Pour chaque Obs = 
            Dim newRow As DataRow
            For Each sta As ClsStation In FormMain.oListObs.lstStations()
                For Each obs As ClsObservation In sta.WhatLst()
                    newRow = table.NewRow
                    newRow(0) = sta.Whendate()
                    newRow(1) = obs.WhatTaxonName()
                    newRow(2) = obs.ProtocolName
                    newRow(3) = obs.Field1Name
                    newRow(4) = obs.Field1Type
                    newRow(5) = obs.Field1Unit
                    newRow(6) = obs.Field1Value
                    newRow(7) = obs.Field2Name
                    newRow(8) = obs.Field2Type
                    newRow(9) = obs.Field2Unit
                    newRow(10) = obs.Field2Value
                    ' newRow(3) = obs.WhatAbundancy()
                    'newRow(4) = obs.WhatDistance()
                    'newRow(5) = obs.WhatOccupiedNest()
                    newRow(11) = sta.WhereName()
                    newRow(12) = sta.WhereLon()
                    newRow(13) = sta.WhereLat()
                    newRow(14) = sta.WhereAlt()
                    newRow(15) = sta.WhereAccuracy()
                    newRow(16) = sta.WhereSiteName()
                    newRow(17) = sta.WhereComments()
                    newRow(18) = sta.WhoFW1Name()
                    newRow(19) = sta.WhoFW2Name()
                    newRow(20) = sta.WhoFWNb()
                    table.Rows.Add(newRow)
                Next
            Next
            Return table
        Catch ex As Exception
            Throw New Exception("Impossible de générer la table des observations: " & ex.Message)
        End Try 
    End Function

    '""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    'Fonction qui renvoie une chaine de caractère correspondant à la liste des observations au format KML
    'IN :
    '   sObsXML : Liste des observations au format XML
    'OUT : 
    '   String : KML
    '<Placemark>
    '<name>Simple placemark</name>
    '<description>Attached to the ground. Intelligently places itself 
    '   at the height of the underlying terrain.</description>
    '<TimeStamp>
    '   <when>2009-02-01</when>
    '</TimeStamp>
    '<Point>
    '  <coordinates>-122.0822035425683,37.42228990140251,0</coordinates>
    '</Point>
    '</Placemark>
    '""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    Public Function ExportObsXMLToKML(ByVal sObsXML As String) As String
        Dim m_nodelist As XmlNodeList
        Dim m_node As XmlNode
        Dim m_xmld As XmlDocument
        Dim output As New StringWriter()
        Dim xsettings As New XmlWriterSettings()
        Dim XmlWriter As XmlWriter
        Try
            'Création du document XML d'entré
            m_xmld = New XmlDocument()
            'Chargement du fichier XML
            Dim m_sr As New System.IO.StringReader(sObsXML)
            m_xmld.Load(m_sr)
            'Parametrage du fichier XML de sortie
            xsettings.Indent = True
            xsettings.NewLineOnAttributes = True
            xsettings.Encoding = New UTF8Encoding(False)
            'Entête du fichier
            XmlWriter = XmlWriter.Create(output, xsettings)
            XmlWriter.WriteProcessingInstruction("xml", "version=""1.0"" encoding=""utf-8"" standalone=""no"" ")
            XmlWriter.WriteStartElement("kml")
            XmlWriter.WriteElementString("xmlns", "http://www.opengis.net/kml/2.2")
            XmlWriter.WriteStartElement("Document")
            'Pour chaque relevé Création d'un nouveau Placemark
            'Pour chaque relevé Création d'un nouveau Wpt
            m_nodelist = m_xmld.SelectNodes("/RELEVES/RELEVE")
            For Each m_node In m_nodelist
                XmlWriter.WriteStartElement("Placemark")
                XmlWriter.WriteElementString("name", m_node.SelectNodes("./WHERE/NAME").Item(0).InnerText())
                'Pour chaque obs comment = taxon 1; ...;taxon i; ...; taxon n
                Dim m_nodelistObs As XmlNodeList
                Dim m_nodeObs As XmlNode
                Dim sCmt As String = ""
                m_nodelistObs = m_node.SelectNodes("./WHAT")
                For Each m_nodeObs In m_nodelistObs
                    sCmt = sCmt & "; " & m_nodeObs.SelectNodes("./TAXON/TAXON_NAME").Item(0).InnerText
                Next
                If sCmt <> "" Then
                    sCmt = Right(sCmt, sCmt.Length - 2)
                    sCmt = "Espece(s) : " & sCmt & vbCrLf
                End If
                sCmt = sCmt & "Observateurs : " & m_node.SelectNodes("./WHO/FIELDWORKER1_NAME").Item(0).InnerText() & ";"
                sCmt = sCmt & m_node.SelectNodes("./WHO/FIELDWORKER2_NAME").Item(0).InnerText() & vbCrLf
                XmlWriter.WriteElementString("description", sCmt)
                XmlWriter.WriteStartElement("TimeStamp")
                Dim ddate As DateTime = m_node.SelectNodes("./WHEN/DATE").Item(0).InnerText()
                XmlWriter.WriteElementString("when", ddate.ToString("s") & "Z")
                XmlWriter.WriteEndElement()
                XmlWriter.WriteStartElement("Point")
                XmlWriter.WriteElementString("coordinates", m_node.SelectNodes("./WHERE/LONGITUDE").Item(0).InnerText() & "," & m_node.SelectNodes("./WHERE/LATITUDE").Item(0).InnerText() & "," _
                                             & "," & m_node.SelectNodes("./WHERE/ELEVATION").Item(0).InnerText())
                XmlWriter.WriteEndElement()
                XmlWriter.WriteEndElement()
            Next
            XmlWriter.WriteEndElement()
            XmlWriter.WriteEndDocument()
            XmlWriter.Flush()
            Return output.ToString()
        Catch ex As Exception
            Throw New Exception("Impossible de générer le fichier KML: " & ex.Message)
        End Try
    End Function

    '""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    'Fonction qui renvoie une chaine de caractère correspondant à la liste des observations au format CSV
    'IN :
    '   sObsXML : Liste des observations au format XML
    'OUT : 
    '   String : CSV
    '""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    Public Function ExportObsXMLToCSV(ByVal sObsXML As String) As String
        Dim output As String = ""
        Dim m_xmld As XmlDocument
        Dim m_nodelist As XmlNodeList
        Dim m_node As XmlNode
        Dim m_nodelistObs As XmlNodeList
        Dim m_nodeObs As XmlNode
        Try
            output = "date; id taxon; taxon; nb ind.; adundancy;distance;occupied; wpt; lat; lon; ele; accuracy; dop; comments; id site; site; id Field Worker 1;Field Worker 1 ; id Field Worker 2; Field Worker 2; Nb FW  " & vbCrLf
            'Création du document XML d'entré
            m_xmld = New XmlDocument()
            'Chargement du fichier XML
            Dim m_sr As New System.IO.StringReader(sObsXML)
            m_xmld.Load(m_sr)
            'Pour chaque relevé Création d'un nouveau Wpt
            m_nodelist = m_xmld.SelectNodes("/RELEVES/RELEVE")
            For Each m_node In m_nodelist
                m_nodelistObs = m_node.SelectNodes("./WHAT")
                For Each m_nodeObs In m_nodelistObs
                    output = output & m_node.SelectNodes("./WHEN/DATE").Item(0).InnerText() & ";"
                    output = output & m_nodeObs.SelectNodes("./TAXON_ID").Item(0).InnerText() & ";"
                    output = output & m_nodeObs.SelectNodes("./TAXON_NAME").Item(0).InnerText() & ";"
                    output = output & m_nodeObs.SelectNodes("./NUMBER").Item(0).InnerText() & ";"
                    output = output & m_nodeObs.SelectNodes("./ABUNDANCY").Item(0).InnerText() & ";"
                    output = output & m_nodeObs.SelectNodes("./DISTANCE").Item(0).InnerText() & ";" ' rajout de protocole de Zambra
                    output = output & m_nodeObs.SelectNodes("./OCCUPE").Item(0).InnerText() & ";" ' rajout de protocole de Zambra
                    output = output & m_node.SelectNodes("./WHERE/NAME").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHERE/LATITUDE").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHERE/LONGITUDE").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHERE/ELEVATION").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHERE/ACCURACY").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHERE/DOP").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHERE/COMMENTS").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHERE/SITE_ID").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHERE/SITE_NAME").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHO/FIELDWORKER1_ID").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHO/FIELDWORKER1_NAME").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHO/FIELDWORKER2_ID").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHO/FIELDWORKER2_NAME").Item(0).InnerText() & ";"
                    output = output & m_node.SelectNodes("./WHO").Item(0).Attributes.GetNamedItem("NB").Value & vbCrLf
                Next
            Next
            Return output
        Catch ex As Exception
            Throw New Exception("Impossible de générer le fichier CSV: " & ex.Message)
        End Try
    End Function

    '""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    'Fonction qui renvoie une chaine de caractère correspondant à la liste des observations au format GPX
    'IN :
    '   sObsXML : Liste des observations au format XML
    'OUT : 
    '   String : GPX 
    '<wpt lat="39.921055008" lon="3.054223107">
    '   <ele>12.863281</ele>
    '   <time>2005-05-16T11:49:06Z</time>
    '   <name>Cala Sant Vicenç - Mallorca</name>
    '   <cmt> xsd:string </cmt> 
    '</wpt>
    '""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    Public Function ExportObsXMLToGPX(ByVal sObsXML As String) As String
        Dim m_xmld As XmlDocument
        Dim m_nodelist As XmlNodeList
        Dim m_node As XmlNode
        Dim output As New StringWriter()
        Dim xsettings As New XmlWriterSettings()
        Dim XmlWriter As XmlWriter
        Try
            'Création du document XML d'entré
            m_xmld = New XmlDocument()
            'Chargement du fichier XML
            Dim m_sr As New System.IO.StringReader(sObsXML)
            m_xmld.Load(m_sr)
            'Parametrage du fichier XML de sortie
            xsettings.Indent = True
            xsettings.NewLineOnAttributes = True
            xsettings.Encoding = New UTF8Encoding(False)
            'Entête du fichier
            XmlWriter = XmlWriter.Create(output, xsettings)
            XmlWriter.WriteProcessingInstruction("xml", "version=""1.0"" encoding=""utf-8"" standalone=""no"" ")
            XmlWriter.WriteStartElement("gpx")
            'Pour chaque relevé Création d'un nouveau Wpt
            m_nodelist = m_xmld.SelectNodes("/RELEVES/RELEVE")
            For Each m_node In m_nodelist
                XmlWriter.WriteStartElement("wpt")
                XmlWriter.WriteAttributeString("lat", m_node.SelectNodes("./WHERE/LATITUDE").Item(0).InnerText())
                XmlWriter.WriteAttributeString("lon", m_node.SelectNodes("./WHERE/LONGITUDE").Item(0).InnerText())
                XmlWriter.WriteElementString("ele", m_node.SelectNodes("./WHERE/ELEVATION").Item(0).InnerText())
                XmlWriter.WriteElementString("time", m_node.SelectNodes("./WHEN/DATE").Item(0).InnerText())
                XmlWriter.WriteElementString("name", m_node.SelectNodes("./WHERE/NAME").Item(0).InnerText())
                'Pour chaque obs comment = taxon 1; ...;taxon i; ...; taxon n
                Dim m_nodelistObs As XmlNodeList
                Dim m_nodeObs As XmlNode
                Dim sCmt As String = ""
                m_nodelistObs = m_node.SelectNodes("./WHAT")
                For Each m_nodeObs In m_nodelistObs
                    sCmt = sCmt & "; " & m_nodeObs.SelectNodes("./TAXON/TAXON_NAME").Item(0).InnerText
                Next
                If sCmt <> "" Then
                    sCmt = Right(sCmt, sCmt.Length - 2)
                End If
                XmlWriter.WriteElementString("cmt", sCmt)
                XmlWriter.WriteEndElement()
            Next
            XmlWriter.WriteEndElement()
            XmlWriter.WriteEndDocument()
            XmlWriter.Flush()
            Return output.ToString()
        Catch ex As Exception
            Throw New Exception("Impossible de générer le fichier GPS: " & ex.Message)
        End Try
    End Function


    ' fonction pour convertir les angles DMS - > degré décimal

    Public Function conversionAngle(ByVal lat As String) As String

        Dim i1, i2, i3, l As Short
        Dim valDeg, valMin, valSec, orientation, strValDegDec, strValDegDec2, strDD As String
        Dim valDegDec As Double
        i1 = lat.IndexOf("°")
        i2 = lat.IndexOf("'")
        i3 = lat.IndexOf(",")
        l = lat.Length
        valDeg = lat.Substring(0, i1)
        valMin = lat.Substring((i1 + 1), (i2 - i1 - 1))
        'valSec = lat.Substring(i2 + 1, l - i2 - 3)
        valSec = lat.Substring(i2 + 1, i3 - i2 - 1) & "," & lat.Substring(i3 + 1, l - i3 - 3)
        orientation = lat.Substring(l - 1, 1)
        'la partie décimale
        valDegDec = CDbl(valMin) / 60 + CDbl(valSec) / 3600

        ' tronquer la partie décimale à 5 chiffres après virgule et remplacer la virgule par un point
        strValDegDec = Str(valDegDec)

        strValDegDec2 = strValDegDec.Substring(2, 6)

        strDD = valDeg & strValDegDec2

        ' si l'orientation est sud ou ouest ajouter un signe négatif avant la valeur (S, W)

        If orientation = "S" Or orientation = "s" Or orientation = "W" Or orientation = "w" Then
            strDD = "-" & strDD
        End If

        strDD = Replace(strDD, ".", ",")
        strDD = CType(strDD, Double)
        Return strDD

    End Function
    ' fonction qui gére la prise de vues par l'appareil photo integré 

    Function PrendrePhoto() As String

        Dim strDossierRacine As String
        Dim i As Short

        strDossierRacine = "\My Documents\Photos_e-releve"  'dossier racine
        Try

            ' si ce dossier n'existe pas il faut le creer
            CreerDossier(strDossierRacine)
            ' Pour mieux organiser les photos, dans le dossier racine créer un dossier par strJour de prise de données 
            ' le nom du dossier est la date du strJour AAAA_MM_JJ
            Dim strAnnee, strAnneeAA, strMois, strJour, strNomDossierCourant, strPathDossierCourant, strNomPhoto As String
            Dim intstrMois, intstrJour As Short
            strAnnee = Date.Now.Year.ToString
            strAnneeAA = strAnnee.Substring(2, 2)
            intstrMois = Date.Now.Month
            intstrJour = Date.Now.Day
            ' afficher le strMois avec le format MM
            If intstrMois < 10 Then
                strMois = "0" & intstrMois
            Else : strMois = intstrMois
            End If
            ' afficher le strJour avec le format JJ
            If intstrJour < 10 Then
                strJour = "0" & intstrJour
            Else : strJour = intstrJour
            End If
            strNomDossierCourant = strAnnee & "_" & strMois & "_" & strJour
            ' si ce dossier n'existe pas il faut le creer
            strPathDossierCourant = "\My Documents\Photos_e-releve\" & strNomDossierCourant
            CreerDossier(strPathDossierCourant)
            ' chaque photo a comme nom de fichier la concaténation de la chaine " date (AAAAMMJJ) + photo + numero ' variable i)"
            'compter le nombre de fichiers photos dans le dossier courant

            i = System.IO.Directory.GetFiles(strPathDossierCourant).Length   '+1

            Dim bExiste As Boolean = True

            ' pour eviter d'ecraser les fichiers en cas de suppression, verifier la nom existance du nom de fichier attribué
            If System.IO.File.Exists(strPathDossierCourant & "\" & strAnneeAA & strMois & strJour & "_photo_" & i + 1 & ".jpg") Then

                Do While bExiste = True
                    i = i + 1
                    bExiste = System.IO.File.Exists(strPathDossierCourant & "\" & strAnneeAA & strMois & strJour & "_photo_" & i + 1 & ".jpg")

                Loop

            End If

            strNomPhoto = strAnneeAA & strMois & strJour & "_photo_" & i + 1 & ".jpg"

            Dim wCapture As New CameraCaptureDialog
            With wCapture
                .InitialDirectory = strPathDossierCourant
                .DefaultFileName = strNomPhoto
                .Mode = CameraCaptureMode.Still
                .Owner = frmEntryChoixTaxon
                .StillQuality = CameraCaptureStillQuality.High
                .Title = "Photo_e-releve"

            End With

            ' lancer la capture
            Dim r As DialogResult = wCapture.ShowDialog

            If r = Windows.Forms.DialogResult.OK Then
                Dim wSource As String = wCapture.FileName
                MsgBox("Photo enregistrée!" & vbCrLf & "Nom du fichier:" & wSource)

            End If
            wCapture.Dispose()
            Return strNomPhoto
        Catch ex As Exception
            MsgBox("Erreur, appareil photo")
            Return "Null"
        End Try
    End Function



    Function PrendrePhotoGeoref() As String

        Dim strDossierRacine As String
        Dim i As Short

        strDossierRacine = "\My Documents\Photos_Georef"  'dossier racine
        Try

            ' si ce dossier n'existe pas il faut le creer
            CreerDossier(strDossierRacine)
            Dim strNomPhoto As String

            ' chaque photo a comme nom de fichier la concaténation de la chaine "  photo + numero ' variable i)"
            'compter le nombre de fichiers photos dans le dossier courant

            i = System.IO.Directory.GetFiles(strDossierRacine).Length   '+1

            Dim bExiste As Boolean = True

            ' pour eviter d'ecraser les fichiers en cas de suppression, verifier la nom existance du nom de fichier attribué
            If System.IO.File.Exists(strDossierRacine & "\" & "photo_" & (CInt(i / 2) + 1) & ".jpg") Then

                Do While bExiste = True
                    i = i + 1
                    bExiste = System.IO.File.Exists(strDossierRacine & "\" & "photo_" & (CInt(i / 2) + 1) & ".jpg")

                Loop

            End If

            strNomPhoto = "photo_" & (CInt(i / 2) + 1) & ".jpg"

            Dim wCapture As New CameraCaptureDialog
            With wCapture
                .InitialDirectory = strDossierRacine
                .DefaultFileName = strNomPhoto
                .Mode = CameraCaptureMode.Still
                .Owner = frmEntryChoixTaxon
                .StillQuality = CameraCaptureStillQuality.High
                .Title = "Photo_e-releve"

            End With

            ' lancer la capture
            Dim r As DialogResult = wCapture.ShowDialog

            If r = Windows.Forms.DialogResult.OK Then
                Dim wSource As String = wCapture.FileName
                ' MsgBox("Photo enregistrée!" & vbCrLf & "Nom du fichier:" & wSource)
                frmPhotoGeoref.LblAffichage.Text = "Photo enregistrée! Nom du fichier:" & wSource
            End If
            wCapture.Dispose()
            Return strNomPhoto
        Catch ex As Exception
            MsgBox("Erreur, appareil photo")
            Return "Null"
        End Try
    End Function



    ' sub pour gerer les doosiers ou stocker les photos prises par l'appareil

    Sub CreerDossier(ByVal CheminDossier As String)
        If Not System.IO.Directory.Exists(CheminDossier) Then
            Try
                System.IO.Directory.CreateDirectory(CheminDossier)
            Catch ex As Exception
                MsgBox("Impossible de créer le doosier photos ! ", MsgBoxStyle.Critical)
                Exit Sub
            End Try
        End If
    End Sub
End Module
